//
//  JRASRManager.m
//  ASRMemo
//
//  Created by YangShuai on 16/9/26.
//  Copyright © 2016年 ys. All rights reserved.
//

#import "JRASRManager.h"
#import "ASR.h"
#include <stdio.h>
#import "ASRDebugLog.h"
#import "ASRPcmRecorder.h"
#import "ASRKeyDefine.h"
#import "TLRecorderMp3.h"
#import "TLSoundPlayer.h"
#import "ConstDefine.h"

@interface JRASRManager ()<ASRPcmRecorderDelegate,TLSoundPlayerDelegate>
@property (nonatomic,strong) ASRPcmRecorder *recorder;
@property (nonatomic,strong) NSMutableData *m_data;
@end

static JRASRManager *defaultASRManager = nil;
@implementation JRASRManager{
    dispatch_queue_t _ASRQueue;
    //
    ASR      *m_pDetailASR;
    TLRecorderMp3* mp3recoder;
    //
    NSString *_ASRDirPath;
}

-(instancetype)init{
    self = [super init];
    if (self) {
        //初始化数据包
        [self initializeASRData];
        //
        _ASRQueue = dispatch_queue_create("JRASRQueue", DISPATCH_QUEUE_CONCURRENT);
        m_pDetailASR = [[ASR alloc] init];
        [m_pDetailASR createWithFolder:@"pcm" license:ASR_LICENSE];
        self.m_data = [[NSMutableData alloc]init];
        mp3recoder = [TLRecorderMp3 new];
        //
        NSString *cachesDir = [self getCacheDirFilePath];
        _ASRDirPath = [cachesDir stringByAppendingPathComponent:ASRRecordDir];
        BOOL isDir;
        BOOL isFileExist = [[NSFileManager defaultManager] fileExistsAtPath:_ASRDirPath isDirectory:&isDir];
        if (!isDir && isFileExist) {
            [[NSFileManager defaultManager] removeItemAtPath:_ASRDirPath error:nil];
        }
        if (!isDir || !isFileExist) {
            [[NSFileManager defaultManager] createDirectoryAtPath:_ASRDirPath withIntermediateDirectories:YES attributes:nil error:NULL];
        }
    }
    return self;
}
//初始化数据包
-(void)initializeASRData{
    NSString* fPath = [[DataProcessing shareSingle].supportFilesDirector stringByAppendingPathComponent:@"asr.dat"];
    if ([[NSFileManager defaultManager] fileExistsAtPath:fPath]) {
        [ASREngine initEngine:[NSData dataWithContentsOfFile:fPath]];
    }
}

//
+ (JRASRManager*)defaultManager{
    if (defaultASRManager == nil) {
        @synchronized (self) {
            defaultASRManager = [[JRASRManager alloc] init];
        }
    }
    return defaultASRManager;
}
//评测
-(void)getDetailString:(NSString *)sSentence WordArray:(NSArray*)wordArray IsBookEn:(BOOL)isBookEn Completed:(void (^)(NSInteger score,NSArray *detailArray))completed{
    [self stopRecord];
#if __Debug_FollowReadingDataStore
    [self.m_data writeToFile:[NSString stringWithFormat:@"%@/followReading_currentRecord.pcm",[self getCacheDirFilePath]] atomically:YES];
#endif
    dispatch_async(_ASRQueue, ^{
        [self getDetailString:sSentence WordArray:wordArray ofData:(short *)_m_data.bytes count:_m_data.length / 2 inLang:0x0804 isPinYin:FALSE IsBookEn:isBookEn Complete:^(NSInteger score, NSArray *detailArray) {
            if (completed) {
                completed(score, detailArray);
            }
        }];
    });
}

//开始录音
-(NSString*)startRecordWithBookId:(NSInteger)bookId PageId:(NSInteger)pageId entenceId:(NSInteger)sentenceId RecordTimestamp:(long long)timestamp{
    [self stopPlay];
    //
    self.recorder = [[ASRPcmRecorder alloc]init];
    self.recorder.delegate = self;
    [self.recorder setAudioFormat:8000 theBitsPerChannel:16 theChannelsPerFrame:1];
    [self.recorder start];
    [self.recorder getAudioPower];
    //录制mp3
    NSString* relativeFilePath = [self getRelativePathWithBookId:bookId PageId:pageId SentenceId:sentenceId RecordTimestamp:timestamp];
    mp3recoder.filePath = [[DB_NetFollowReading shareSingle] getFullPathWithRelativePath:relativeFilePath];
    [mp3recoder start];
    [self record_AudioCategory];
    return relativeFilePath;
}
//结束录音
-(void)stopRecord{
    [mp3recoder stop];
    [self.recorder stop];
    [self default_AudioCategory];
}

//播放录音
-(void)startPlayRecordWithFullFilePath:(NSString*)fullFilePath{
    [self stopPlay];
    [[TLSoundPlayer shareSingle] playFile:fullFilePath andDelegate:self];
}
//停止播放
-(void)stopPlay{
    [[TLSoundPlayer shareSingle] stopAllFiles_andClean];
}

#pragma mark - 私有方法
-(void)getDetailString:(NSString *)sSentence WordArray:(NSArray*)wordArray ofData:(short *)pData count:(NSInteger)nShortCount inLang:(NSInteger)nLangID isPinYin:(BOOL)fPinYin IsBookEn:(BOOL)isBookEn Complete:(void(^)(NSInteger score,NSArray *detailArray))complete
{
    if (m_pDetailASR == nil) {
        return;
    }
    //
    [m_pDetailASR setParameter:ASR_PARM_MAX_END_SIL value:3000];
    [m_pDetailASR loadGrammar:sSentence langID:(int)nLangID isPinYin:fPinYin];
    if (![m_pDetailASR start]){
        return;
    }
    //处理数组
    NSMutableArray* wordArrayNoSpace = [NSMutableArray new];
    for (NSString* word in wordArray) {
       NSString* noSpaceWord = [word stringByReplacingOccurrencesOfString:@" " withString:@""];
        [wordArrayNoSpace addObject:noSpaceWord];
    }
    wordArray = wordArrayNoSpace;
    //
    [m_pDetailASR setData:pData count:nShortCount];
    NSInteger nCount = [m_pDetailASR getResultCount];
    NSString *pRes = [NSString stringWithFormat:@"nCount=%d\n", (int)nCount];
    NSNumber *ptBegin = [m_pDetailASR getSpeechBegin];
    NSNumber *ptEnd = [m_pDetailASR getSpeechEnd];
    float fBegin = [ptBegin floatValue];
    float fEnd = [ptEnd floatValue];
    NSString *sTime = [NSString stringWithFormat:@"all time:[%f, %f]\n", fBegin, fEnd];
    pRes = [pRes stringByAppendingString:sTime];
    NSArray *pResArr = [m_pDetailASR getWordScoreDetail];
    [m_pDetailASR stop];
    int nMaxCount = (int)(pResArr!=nil ? pResArr.count : 0);
    //
    NSInteger totleScore = 0;
    NSInteger score = 0;
    //
    NSMutableArray *pResArr_m = [NSMutableArray arrayWithArray:[m_pDetailASR getWordScoreDetail]];
    NSMutableArray *pResArr_final = [NSMutableArray new];
    if (wordArray.count >= pResArr.count) {
        for (int i = 0; i < wordArray.count; i++) {
            NSString* word = wordArray[i];
            //处理标点符号的占位
            word = [word stringByReplacingOccurrencesOfString:@" " withString:@""];
            if ([word isEqualToString:@""]) {
                ASRWordScore* oneScore = [[ASRWordScore alloc] init];
                oneScore.mWord = word;
                oneScore.mScore = 100;
                oneScore.mBeginTime = @(0);
                oneScore.mEndTime = @(0);
                [pResArr_final addObject:oneScore];
                continue;
            }
            //正常文字评测结果
            ASRWordScore* oneScore = [pResArr_m firstObject];
            NSString* mWord = oneScore.mWord;
            mWord = [oneScore.mWord stringByReplacingOccurrencesOfString:@" " withString:@""];
            if (oneScore && [word rangeOfString:mWord].location != NSNotFound) {
                [pResArr_final addObject:oneScore];
                [pResArr_m removeObject:oneScore];
            }else{
                ASRWordScore* oneScore = [self creatOneScoreZeroWithWord:word];
                [pResArr_final addObject:oneScore];
            }
        }
    }
    //
    if (wordArray.count == pResArr_final.count) {
        for (int i = 0; i < wordArray.count; i++) {
            ASRWordScore* oneScore = pResArr_final[i];
            NSString* word = wordArray[i];
            oneScore.mWord = word;
        }
    }
    //
    for(int i=0; i<nMaxCount; i++) {
        ASRWordScore *itemScore = (ASRWordScore *)[pResArr objectAtIndex:i];
        NSInteger oneScore = itemScore.mScore;
        totleScore += oneScore;
    }
    NSInteger ASRCount = wordArray.count;
    for (NSString* word in wordArray) {
        if ([word isEqualToString:@""]) {
            ASRCount --;
        }
    }
    if(ASRCount > 0){
        score = totleScore / ASRCount;
    }
    if (complete) {
        complete(score, pResArr_final);
    }
    self.m_data = [NSMutableData new];
}
//创建一个空的评测结果
-(ASRWordScore*)creatOneScoreZeroWithWord:(NSString*)word{
    ASRWordScore* oneScore = [[ASRWordScore alloc] init];
    oneScore.mWord = word;
    oneScore.mScore = 0;
    oneScore.mBeginTime = @(0);
    oneScore.mEndTime = @(0);
    return oneScore;
}
//获取cache目录跟地址
-(NSString*)getCacheDirFilePath{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachesDir = [paths objectAtIndex:0];
    return cachesDir;
}

/** 生成相对路径 */
-(NSString*)getRelativePathWithBookId:(NSInteger)bookId PageId:(NSInteger)pageId SentenceId:(NSInteger)sentenceId RecordTimestamp:(long long)timestamp{
    UserInfo* uinfo = [CacheData shareSingle].getUserLoginInfo;
    return [NSString stringWithFormat:@"/%@/%@/%@/%@/%@/%@.mp3",ASRRecordDir,@(uinfo.uid),@(bookId),@(pageId),@(sentenceId),@(timestamp)];
}

#pragma mark- 录音回调

/*
 * @回调音频数据，buffer表示音频数据，size表示音频的长度
 */
- (void) onReturnBuffer: (const void *)buffer bufferSize:(int)size
{
    NSData *data = [NSData dataWithBytes:buffer length:size];
    [self.m_data appendData:data];
}

/*
 * @音频的错误码
 */
- (void) onRecorderError:(ASRPcmRecorder*)recoder theError:(int) error
{
    NSLog(@"录音出错");
}
/*
 * @音频的能量 -160 - 0 之间
 */
- (void) onRecorderPower:(float)power
{
    //NSLog(@"%@",@(power));
}

-(void)dealloc{
    [mp3recoder stop],mp3recoder = nil;
}

//
- (void)default_AudioCategory
{
    //    //系统键控制静音
    //    //[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
    //    //播放声音互斥 其他应用
    //    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:nil];
    
    //    //扬声器播放 将关闭系统键控制静音
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    UInt32 category = kAudioSessionCategory_MediaPlayback;
    AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
    
    //    //听筒播放 与 扬声器播放 互斥
    //    //[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
}

- (void)record_AudioCategory
{
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    UInt32 category = kAudioSessionCategory_PlayAndRecord;
    AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
}

#pragma mark - TLSoundPlayerDelegate
- (void)tlSoundPlayerDidFinishPlayingFile:(NSString*)fileFullPath player:(AVAudioPlayer *)player{
    [[TLSoundPlayer shareSingle] stopFilePlay_andClean:fileFullPath];
}
@end
